/**
 * @p.md
 * 
 * Supervision 模块，定义 Actor 故障处理策略
 */
import { PID } from './pid';

/**
 * 监督指令枚举，定义了处理 Actor 故障的策略
 */
export enum SupervisorDirective {
  /**
   * 恢复 Actor 处理，不做任何改变
   */
  Resume,
  
  /**
   * 重启 Actor，创建新的 Actor 实例但保持 PID 不变
   */
  Restart,
  
  /**
   * 停止 Actor，终止 Actor 进程
   */
  Stop,
  
  /**
   * 升级故障，将故障传递给父 Actor 处理
   */
  Escalate
}

/**
 * 监督策略枚举，定义了监督策略的类型
 */
export enum SupervisorStrategyType {
  /**
   * 一对一策略：只影响发生故障的 Actor
   */
  OneForOne = 'one-for-one',
  
  /**
   * 一对全策略：影响监督者的所有子 Actor
   */
  OneForAll = 'one-for-all',
  
  /**
   * 剩余策略：影响故障 Actor 之后创建的所有 Actor
   */
  RestForOne = 'rest-for-one'
}

/**
 * 监督者接口，定义了处理 Actor 故障的行为
 */
export interface Supervisor {
  /**
   * 处理子 Actor 失败
   * @param pid 失败的 Actor PID
   * @param reason 失败原因
   */
  handleFailure(pid: PID, reason: Error): SupervisorDirective;
}

/**
 * 监督者配置
 */
export interface SupervisorConfig {
  maxRetries?: number;
  withinTimeSpan?: number;
  strategyType?: SupervisorStrategyType;
}

/**
 * 默认监督者，提供默认的故障处理策略
 */
export class DefaultSupervisor implements Supervisor {
  /**
   * 处理子 Actor 失败
   * @param pid 失败的 Actor PID
   * @param reason 失败原因
   */
  handleFailure(pid: PID, reason: Error): SupervisorDirective {
    console.warn(`[DefaultSupervisor] Actor failure: ${pid.id}@${pid.address}`, reason);
    // 默认策略是重启 Actor
    return SupervisorDirective.Restart;
  }
}

/**
 * 总是重启监督者，无论发生什么故障都重启 Actor
 */
export class AlwaysRestartSupervisor implements Supervisor {
  /**
   * 处理子 Actor 失败，始终重启
   * @param pid 失败的 Actor PID
   * @param reason 失败原因
   */
  handleFailure(pid: PID, reason: Error): SupervisorDirective {
    return SupervisorDirective.Restart;
  }
}

/**
 * 总是恢复监督者，无论发生什么故障都恢复 Actor
 */
export class AlwaysResumeSupervisor implements Supervisor {
  /**
   * 处理子 Actor 失败，始终恢复
   * @param pid 失败的 Actor PID
   * @param reason 失败原因
   */
  handleFailure(pid: PID, reason: Error): SupervisorDirective {
    return SupervisorDirective.Resume;
  }
}

/**
 * 总是停止监督者，无论发生什么故障都停止 Actor
 */
export class AlwaysStopSupervisor implements Supervisor {
  /**
   * 处理子 Actor 失败，始终停止
   * @param pid 失败的 Actor PID
   * @param reason 失败原因
   */
  handleFailure(pid: PID, reason: Error): SupervisorDirective {
    return SupervisorDirective.Stop;
  }
}

/**
 * 总是升级监督者，无论发生什么故障都升级给父 Actor
 */
export class AlwaysEscalateSupervisor implements Supervisor {
  /**
   * 处理子 Actor 失败，始终升级
   * @param pid 失败的 Actor PID
   * @param reason 失败原因
   */
  handleFailure(pid: PID, reason: Error): SupervisorDirective {
    return SupervisorDirective.Escalate;
  }
}

/**
 * 指数退避监督者，随着故障次数增加，延长重试间隔
 */
export class ExponentialBackoffSupervisor implements Supervisor {
  private retryCount: Map<string, number> = new Map();
  private lastFailureTime: Map<string, number> = new Map();
  private readonly maxRetries: number;
  private readonly backoffWindow: number;
  
  /**
   * 创建指数退避监督者
   * @param maxRetries 最大重试次数，默认为10
   * @param backoffWindow 退避时间窗口（毫秒），默认为10秒
   */
  constructor(maxRetries: number = 10, backoffWindow: number = 10000) {
    this.maxRetries = maxRetries;
    this.backoffWindow = backoffWindow;
  }
  
  /**
   * 处理子 Actor 失败，使用指数退避策略
   * @param pid 失败的 Actor PID
   * @param reason 失败原因
   */
  handleFailure(pid: PID, reason: Error): SupervisorDirective {
    const key = `${pid.id}@${pid.address}`;
    const now = Date.now();
    const lastFailure = this.lastFailureTime.get(key) || 0;
    
    // 如果超过了时间窗口，重置重试计数
    if (now - lastFailure > this.backoffWindow) {
      this.retryCount.set(key, 0);
    }
    
    // 更新最后故障时间
    this.lastFailureTime.set(key, now);
    
    // 增加重试计数
    const currentRetries = (this.retryCount.get(key) || 0) + 1;
    this.retryCount.set(key, currentRetries);
    
    // 如果超过最大重试次数，停止 Actor
    if (currentRetries > this.maxRetries) {
      console.warn(`[ExponentialBackoffSupervisor] Max retries exceeded for ${key}, stopping actor`);
      return SupervisorDirective.Stop;
    }
    
    console.info(`[ExponentialBackoffSupervisor] Restarting actor ${key}, retry ${currentRetries}/${this.maxRetries}`);
    return SupervisorDirective.Restart;
  }
}

/**
 * 监督者工厂，提供创建各种监督者的方法
 */
export const Supervisors = {
  /**
   * 获取默认监督者
   */
  defaultSupervisor(): Supervisor {
    return new DefaultSupervisor();
  },
  
  /**
   * 获取总是重启监督者
   */
  alwaysRestart(): Supervisor {
    return new AlwaysRestartSupervisor();
  },
  
  /**
   * 获取总是恢复监督者
   */
  alwaysResume(): Supervisor {
    return new AlwaysResumeSupervisor();
  },
  
  /**
   * 获取总是停止监督者
   */
  alwaysStop(): Supervisor {
    return new AlwaysStopSupervisor();
  },
  
  /**
   * 获取总是升级监督者
   */
  alwaysEscalate(): Supervisor {
    return new AlwaysEscalateSupervisor();
  },
  
  /**
   * 获取指数退避监督者
   * @param maxRetries 最大重试次数
   * @param backoffWindow 退避时间窗口（毫秒）
   */
  exponentialBackoff(maxRetries?: number, backoffWindow?: number): Supervisor {
    return new ExponentialBackoffSupervisor(maxRetries, backoffWindow);
  }
}; 